package bgplite.io;

import java.io.*;
import java.util.*;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import bgplite.topo.AS;

public class SerializationMaster {

	private byte[] hashValue;
	private String asRelFire;
	private String ipFile;
	private String noPruneFile;

	private static final String SERIALFILE_DIRECTORY = "serial/";
	private static final String SERIALFILE_BGP_EXT = "-BGP.ser";

	public SerializationMaster(String asRelationshipFile, String ipCountFile, String vitalASFile) {
		this.asRelFire = asRelationshipFile;
		this.ipFile = ipCountFile;
		this.noPruneFile = vitalASFile;
		this.buildFileManifest();
	}

	public boolean hasValidBGPSerialFile() {
		String fileName = this.convertHashToBGPFileName();
		File testFileObject = new File(fileName);
		return testFileObject.exists();
	}

	private void buildFileManifest() {
		MessageDigest hasher = null;
		try {
			hasher = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			System.exit(-2);
		}

		this.addToHash(this.asRelFire, hasher);
		this.addToHash(this.ipFile, hasher);
		this.addToHash(this.noPruneFile, hasher);

		this.hashValue = hasher.digest();
	}

	private void addToHash(String fileName, MessageDigest hashObject) {
		try {
			BufferedReader confFile = new BufferedReader(new FileReader(
					fileName));
			while (confFile.ready()) {
				hashObject.update(confFile.readLine().getBytes());
			}
			confFile.close();
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(-2);
		}

	}

	private String convertHashToFileName() {
		Formatter format = new Formatter();
		for (byte b : this.hashValue) {
			format.format("%02x", b);
		}
		String formatResult = format.toString();
		format.close();
		return SerializationMaster.SERIALFILE_DIRECTORY + formatResult;
	}

	private String convertHashToBGPFileName() {
		return this.convertHashToFileName()
				+ SerializationMaster.SERIALFILE_BGP_EXT;
	}

	public void loadBGPSerialFile(HashMap<Integer, AS> activeTopo) {
		try {
			ObjectInputStream serialIn = new ObjectInputStream(
					new FileInputStream(this.convertHashToBGPFileName()));
			List<Integer> sortedAS = this.buildSortedASNList(activeTopo
					.keySet());
			for (int tASN : sortedAS) {
				activeTopo.get(tASN).loadASFromSerial(serialIn);
			}
			serialIn.close();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(-1);
		}
	}

	public void buildBGPSerialFile(HashMap<Integer, AS> activeTopo) {
		try {
			ObjectOutputStream serialOut = new ObjectOutputStream(
					new FileOutputStream(this.convertHashToBGPFileName()));
			List<Integer> sortedAS = this.buildSortedASNList(activeTopo
					.keySet());
			for (int tASN : sortedAS) {
				activeTopo.get(tASN).saveASToSerial(serialOut);
			}
			serialOut.close();
		} catch (IOException e) {
			e.printStackTrace();
			return;
		}
	}

	private List<Integer> buildSortedASNList(Set<Integer> activeASNs) {
		List<Integer> sortedList = new ArrayList<Integer>();
		sortedList.addAll(activeASNs);
		Collections.sort(sortedList);
		return sortedList;
	}
}
